package filesystem.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class File implements Cloneable, Serializable {

	private static final long serialVersionUID = -2985024558554604396L;

	public static final int FILE = 1;
	public static final int DIRECTORY = 2;
	public static final int ROOT = 3;
	public static final int MAX_SUB_NUMS = 8;

	public static final char EXE = 'e';
	public static final char NORMAL = 'n';
	// **********************
	//members
	private String name;	//filenames or directory names
	private char type;	//file type
	private int attribute;	//define file or directory	1 is file,2 is directory,3 is root
	private int startIndex;	//the start index of FAT
	private int size;	//file size
	private boolean isReadOnly = false;
	private boolean isOpen = false;
	private int fileSize; //文件的实际大小

	private List<File> subFiles = new ArrayList<>(); //sub files list
	private int subDirNums;
	private File parentFile;
	//[0]~[2] filenames
	//[3] file type
	//[4] file attribute
	//[5] start disk index
	//[6]~[7] length of file

	//**********************

	//**********************
	//Construct methods
	public File() {
		;
	}
	public File(String name, char type, int startIndex, int size) {
		this.setName(name);
		this.setType(type);
		this.setAttribute(1);
		this.setStartIndex(startIndex);
		this.setSize(size);
	}

	public File(String name, int startIndex) {
		this.setName(name);
		this.setAttribute(2);
		this.setStartIndex(startIndex);
		this.setType(' ');
		this.setSize(1);
	}

	@Override
	public Object clone() throws CloneNotSupportedException{
		Object obj = super.clone();
		File parentFile = ((File)obj).getParentFile();
		String name = ((File)obj).getName();	//filenames or directory names
		char type = ((File)obj).getType();	//file type
		int attribute = ((File)obj).getAttribute();	//define file or directory	1 is file,2 is directory,3 is root
		int size = ((File)obj).getSize();	//file size
		boolean isReadOnly = ((File)obj).isReadOnly();
		boolean isOpen = ((File)obj).isOpen();
		List<File> subFiles = ((File)obj).getSubFiles(); //sub files list
		int subDirNums = ((File)obj).getSubDirNums();


		((File)obj).setParentFile((File) parentFile);
		((File)obj).setName(name);
		((File)obj).setType(type);
		((File)obj).setAttribute(attribute);
		((File)obj).setSize(size);
		((File)obj).setReadOnly(isReadOnly);
		((File)obj).setOpen(isOpen);
		((File)obj).setSubFiles(subFiles);
		((File)obj).setSubDirNums(subDirNums);
		return obj;
	}

	@Override
	public boolean equals(Object obj) {
		if(this == obj) return true;
		if(obj == null) return false;
		if(this.getClass() != obj.getClass()) return false;

		File file = (File) obj;

		if (attribute != file.attribute) return false;
        if (startIndex != file.startIndex) return false;
        if (size != file.size) return false;
        if (subDirNums != file.subDirNums) return false;
        if (isOpen != file.isOpen) return false;
        if (isReadOnly != file.isReadOnly) return false;
        if (name != null ? !name.equals(file.name) : file.name != null) return false;
        return file != null ? file.equals(file.parentFile) : file.parentFile == null;
	}

	 @Override
	    public int hashCode() {
	        int result = name != null ? name.hashCode() : 0;
	        result = 31 * result + attribute;
	        result = 31 * result + startIndex;
	        result = 31 * result + size;
	        result = 31 * result + subDirNums;
	        result = 31 * result + (isOpen ? 1 : 0);
	        result = 31 * result + (parentFile != null ? parentFile.hashCode() : 0);
	        result = 31 * result + (isReadOnly ? 1 : 0);
	        return result;
	    }

	 @Override
	    public String toString() {
	        return "FileModel{" +
	                "name='" + this.name + "\'" +
	                ", attribute=" + this.attribute +
	                ", startIndex=" + this.startIndex +
	                ", size=" + this.size +
	                ", subDirNums=" + this.subDirNums +
	                ", open=" + this.isOpen +
	                // ", subFiles=" + this.subFiles +
	                ", parentFile=" + this.parentFile +
	                ", ReadOnly=" + this.isReadOnly +
					"}";
		}
		public String getNormalName() {
			if (this.attribute == File.FILE) {
				if (this.type != ' ')
					return this.name+"."+this.type;
			}
			return this.name;
		}

		public boolean isFile() {
			return this.attribute == File.FILE;
		}
		public boolean isDirectory() {
			return this.attribute == File.DIRECTORY || this.attribute == File.ROOT;
		}

	//**********************

	//**********************
	//setters && getters
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public char getType() {
		return type;
	}

	public void setType(char type) {
		this.type = type;
	}

	public int getAttribute() {
		return attribute;
	}

	public void setAttribute(int attribute) {
		this.attribute = attribute;
	}
	public int getStartIndex() {
		return startIndex;
	}

	public void setStartIndex(int startIndex) {
		this.startIndex = startIndex;
	}

	public int getSize() {
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}


	public List<File> getSubFiles() {
		return subFiles;
	}

	public void setSubFiles(List<File> subFiles) {
		this.subFiles = subFiles;
	}

	public int getSubDirNums() {
		return subDirNums;
	}

	public void setSubDirNums(int subDirNums) {
		this.subDirNums = subDirNums;
	}

	public File getParentFile() {
		return parentFile;
	}

	public void setParentFile(File parentFile) {
		this.parentFile = parentFile;
	}

	public boolean isReadOnly() {
		return isReadOnly;
	}

	public void setReadOnly(boolean isReadOnly) {
		this.isReadOnly = isReadOnly;
	}


	public boolean isOpen() {
		return isOpen;
	}

	public void setOpen(boolean isOpen) {
		this.isOpen = isOpen;
	}


	public int getFileSize() {
		return fileSize;
	}

	public void setFileSize(int fileSize) {
		this.fileSize = fileSize;
	}
	//**********************
}
